package com.endpoint.gateway.filters;

import com.endpoint.common.constant.ResponseStatus;
import com.endpoint.common.utils.ResultBean;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.List;

/**
 * @Project: endpoint
 * @Name: AuthGlobalFilter
 * @Author: Jack_Li
 * @Date: 2024/7/3 18:02
 */

@Slf4j
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered  {

    public static final String BEGIN_VISIT_TIME = "begin_visit_time";

    @Override
    public int getOrder() {
        return -1;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取开始访问的时间
        exchange.getAttributes().put(BEGIN_VISIT_TIME, System.currentTimeMillis());

        //1.获取request请求对象
        ServerHttpRequest request = exchange.getRequest();
        log.warn("token：" + request.getHeaders().get("Authorization"));
        //2.获取请求路径
        String requestURI = request.getURI().getPath();
        //3.如果是来 注册 登录 及使用swagger的直接方行
        if(requestURI.contains("/play/")
                || requestURI.contains("/member/register") // 放行会员注册
                || requestURI.contains("/member/login") // 放行会员登录
                || requestURI.contains("/home") // 放行首页
                || requestURI.contains("/search") // 放行搜索
                || requestURI.contains("/book/bookCategory") // 放行分类
                || requestURI.contains("/swagger-ui.html") // 放行swagger
                || requestURI.contains("/v2/api-docs") // 放行swagger
                || requestURI.contains("/swagger-resources/configuration/ui") // 放行swagger
                || requestURI.contains("/swagger-resources") // 放行swagger
                || requestURI.contains("/swagger-resources/configuration/security" ) // 放行swagger
                || requestURI.contains("/book/getBookById")  // 放行小说详情
                || requestURI.contains("/lastChapter/about")  // 放行小说最新章节
                || requestURI.contains("/book/recList")  // 放行同类小说推荐
                || requestURI.contains("/comment/newestList")  // 放行小说最新评论
                || requestURI.contains("/thirdparty/orderPay/notifyUrl")
                || requestURI.contains("/thirdparty/orderPay/returnUrl")
                || requestURI.contains("/isAddToBookshelf")
                || requestURI.contains("addVisitCount")
                || requestURI.contains("/member/memberReadHistory/addReadHistory")
                || requestURI.contains("/book")
        ){
            return handleResponseTime(exchange, chain);
        }

        //取出头信息
        HttpHeaders headers = request.getHeaders();
        List<String> authorizations = headers.get("Authorization");

        if(authorizations == null || authorizations.size() <= 0){
            //如果请求头不包含Authorization 那么拒绝访问
            return access_denied(exchange.getResponse(), ResponseStatus.NO_LOGIN);
        }
        // 获取 token
        String token = authorizations.get(0);
        if(StringUtils.isEmpty(token)){
            //token为空 访问拒绝
            return access_denied(exchange.getResponse(),ResponseStatus.NO_LOGIN);
        }

        return handleResponseTime(exchange, chain);
    }

    private Mono<Void> handleResponseTime(ServerWebExchange exchange, GatewayFilterChain chain) {
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            Long beginVisitTime = exchange.getAttribute(BEGIN_VISIT_TIME);
            if (beginVisitTime != null) {
                log.info("<<<<<<<<<<<<<<<<<<<<<耗计算时>>>>>>>>>>>>>>>>>>>>>");
                log.info("访问携带token：" + exchange.getRequest().getHeaders().get("Authorization"));
                log.info("访问接口主机：" + exchange.getRequest().getURI().getHost());
                log.info("访问接口端口：" + exchange.getRequest().getURI().getPort());
                log.info("访问接口路径：" + exchange.getRequest().getURI().getPath());
                log.info("访问接口请求方法：" + exchange.getRequest().getMethod());
                log.info("访问接口请求参数：" + exchange.getRequest().getURI().getRawQuery());
                log.info("请求耗时：{} 毫秒", System.currentTimeMillis() - beginVisitTime);
                log.info("<<<<<<<<<<<<<<<<<<<<<<分割线>>>>>>>>>>>>>>>>>>>>>>");
                System.out.println();
            }
        }));
    }

    private Mono<Void> access_denied(ServerHttpResponse response, ResponseStatus responseStatus){
        response.setStatusCode(HttpStatus.OK);
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        Flux<DataBuffer> result = Flux.just(getBodyBuffer(response, ResultBean.fail(responseStatus)));
        return response.writeWith(result);
    }

    @SneakyThrows
    private DataBuffer getBodyBuffer(ServerHttpResponse response, ResultBean resultBean) {
        byte[] bytes = new ObjectMapper().writeValueAsBytes(resultBean);
        return response.bufferFactory().wrap(bytes);
    }

}
